package yartiss.service.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.table.AbstractTableModel;

import yartiss.engine.simulation.IEnergyProfile;
import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.ITaskSet;
import yartiss.engine.simulation.system.SystemMetrics;

@SuppressWarnings("serial")
public class TasksSetsTableModel extends AbstractTableModel {
	
	private final List<String> policiesNames = new ArrayList<String>(); 
	private final Map<Integer,TaskSetEntry> sets = new HashMap<Integer, TaskSetEntry>();
	private final List<TaskSetEntry> setslist = new ArrayList<TaskSetEntry>();
	@Override
	public int getRowCount() {
		return sets.size();
	}

	@Override
	public int getColumnCount() {
		return policiesNames.size() + 4;
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		TaskSetEntry entry = setslist.get(rowIndex);
		switch (columnIndex) {
		case 0 : return entry.id;
		case 1 : return entry.isValid;
		case 2 : return entry.U;
		case 3 : return entry.Ue;
		}
		int policyIndex = columnIndex-4;
		return policyIndex >=0 && policyIndex < policiesNames.size() ?  entry.results.get(policiesNames.get(columnIndex-4)) : Result.PENDING;
	}
	
	public TaskSetEntry getRow(int index){
		return setslist.get(index);
	}
	
	public void updateEntry(int id, String policy,ITaskSet set,IEnergyProfile ep,int simDuarion,  Result r){
		TaskSetEntry entry = sets.containsKey(Integer.valueOf(id)) ? sets.get(Integer.valueOf(id)) : new TaskSetEntry(id, set, ep,simDuarion);
		entry.results.put(policy, r);
		addPolicy(policy);
		if(!sets.containsKey(Integer.valueOf(id))){
			sets.put(Integer.valueOf(id), entry);
			setslist.add(entry);
		}
		fireTableDataChanged();
	}
	
	public void addPolicy(String policy){
		if(policiesNames.contains(policy))return;
		policiesNames.add(policy);
	}
	
	@Override
	public String getColumnName(int columnIndex){
		switch (columnIndex) {
		case 0 : return "id";
		case 1 : return "Is Valide";
		case 2 : return "U";
		case 3 : return "Ue";
		}
		int policyIndex = columnIndex-4;
		return policyIndex>=0 && policyIndex < policiesNames.size() ? policiesNames.get(columnIndex-4) : "";
	}
	
	public enum Result {SUCCESS, ENERGY_FAILURE,DEADLINE_MISSED, PENDING};
	public class TaskSetEntry {
		public final  int id;
		public final ITaskSet set;
		public final Map<String, Result> results = new HashMap<String, Result>();
		public final double U;
		public final double Ue;
		public boolean isValid ;
		public final int simulationDura;
		public final IEnergyProfile energyProfile;
		
		public TaskSetEntry(int id, ITaskSet set, IEnergyProfile ep, int simduration){
			this.id = id;
			this.set = set;
			simulationDura = simduration;
			this.energyProfile = ep;
			for (String policy : policiesNames) {
				results.put(policy, Result.PENDING);
			}
			U = SystemMetrics.utilisation(set);
			Ue = SystemMetrics.energyUtilization(set, ep.getPowerRate());
	
			isValid = true;
			isValid = SystemMetrics.isFPTimeFaisible(set);
			if(Ue > 1)isValid = false;
			else {
				for (ITask task : set) {
					if(task.getWcee()/task.getWcet() - energyProfile.getPowerRate() > energyProfile.getMaxEnergyLevel() ){
						isValid = false;
						break;
					}
				}
			}
		}
	}
}
